package com.chunqiu.game.wuziqi.websocket.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ruoyi.common.utils.StringUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Data
public class WuZiQiRoomInfo {

    @JsonIgnore
    private final int SIZE = 20;

    private String id = StringUtils.EMPTY;

    private User user1 = new User();

    private User user2 = new User();

    private List<String> spector = new ArrayList<>();

    private String black = "";

    private String white = "";

    private Map<String, WinInfo> winInfo = new HashMap<>();

    private int roomState = 0;

    private String turnTo = "";


    @JsonIgnore
    private Map<String, String> sessionUserMap = new HashMap<>();

    @JsonIgnore
    private short[][] qiPanInfo = new short[20][20];

    @JsonIgnore
    private List<Map<String, String>> qiPanLog = new ArrayList<>();

    @Data
    static
    class User {

        private String name = "";
        private int status = 0;
    }

    @Data
    static
    class WinInfo {

        private String key = "";

        private String user1 = "";

        private String user2 = "";

        private int user1Score = 0;

        private int user2Score = 0;
    }

    public WUZIQIMessageBody updateRoomInfo(WUZIQIMessageBody wuziqiMessageBody) {
        WUZIQIMessageBody returnValue = new WUZIQIMessageBody();
        String x = wuziqiMessageBody.getX();
        String y = wuziqiMessageBody.getY();
        int xInt = Integer.parseInt(x);
        int yInt = Integer.parseInt(y);
        String operate = wuziqiMessageBody.getOperator();
        WuZiQiRoomInfo roomInfo = wuziqiMessageBody.getValue();
        String otherMessage = wuziqiMessageBody.getOtherMessage();
        String type = wuziqiMessageBody.getType();
        short e;
        switch (type) {
            case "JOIN_USER":
                if (otherMessage.equals("1")) {
                    if (!StringUtils.isEmpty(this.user1.name)) {
                        returnValue.setType("ERROR");
                        returnValue.setOtherMessage("此位置有人");
                        return returnValue;
                    }
                    if (this.user2.name.equals(operate)) {
                        this.user2 = new User();
                    }
                    this.user1.name = operate;
                    this.user1.status = 0;
                } else if (otherMessage.equals("2")) {
                    if (!StringUtils.isEmpty(this.user2.name)) {
                        returnValue.setType("ERROR");
                        returnValue.setOtherMessage("此位置有人");
                        return returnValue;
                    }
                    if (this.user1.name.equals(operate)) {
                        this.user1 = new User();
                    }
                    this.user2.name = operate;
                    this.user2.status = 0;
                }
                this.spector.remove(operate);
                break;
            case "READY":
                if (this.user1.name.equals(operate)) {
                    this.user1.status = 1;
                } else if (this.user2.name.equals(operate)) {
                    this.user2.status = 1;
                } else {
                    log.error("准备信息错误");
                    returnValue.setType("ERROR");
                    returnValue.setOtherMessage("准备信息错误");
                    return returnValue;
                }
                if (this.user1.status == 1 && this.user2.status == 1) {
                    //发送开始信息
                    resetGame();
                    this.roomState = 1;
                    type = "START";
                    if (StringUtils.isEmpty(this.black) && StringUtils.isEmpty(this.white)) {
                        this.black = user1.name;
                        this.white = user2.name;
                    } else if (!StringUtils.isEmpty(this.black) && !StringUtils.isEmpty(this.white)) {
                        String temp = this.black;
                        this.black = this.white;
                        this.white = temp;
                    }
                    this.turnTo = this.black;
                }
                break;
            case "LUOZI":
                if (xInt >= 20 || yInt >= 20) {
                    returnValue.setType("ERROR");
                    returnValue.setOtherMessage("棋盘落点非法");
                    return returnValue;
                }
                String luoziFang = "";
                String turnTo;
                if (this.black.equals(operate)) {
                    e = 1;
                    luoziFang = "black";
                    turnTo = this.white;
                } else if (this.white.equals(operate)) {
                    e = 2;
                    luoziFang = "white";
                    turnTo = this.black;
                } else {
                    returnValue.setType("ERROR");
                    returnValue.setOtherMessage("非玩家");
                    return returnValue;
                }
                if(qiPanInfo[xInt][yInt] == 0){
                    qiPanInfo[xInt][yInt] = e;
                }else{
                    returnValue.setType("ERROR");
                    returnValue.setOtherMessage("此位置已有棋子，请重新选择");
                    return returnValue;
                }
                Map<String, String> map = new HashMap<>();
                map.put("x", xInt + "");
                map.put("y", yInt + "");
                map.put("operate", operate);
                map.put("color", luoziFang);
                boolean isWin = checkWin(xInt, yInt, e);
                if (isWin) {
                    type = "WIN";
                    this.roomState = 2;
                    // 记录胜局
                    User[] users = new User[]{user1, user2};
                    Arrays.sort(users, new Comparator<User>() {
                        @Override
                        public int compare(User o1, User o2) {
                            return o1.name.compareTo(o2.name);
                        }
                    });
                    String key = users[0].name + "-" + users[1].name;
                    WinInfo winInfo = this.winInfo.get(key);
                    if(winInfo == null) {
                        winInfo = new WinInfo();
                        winInfo.key = key;
                        winInfo.user1 = users[0].name;
                        winInfo.user2 = users[1].name;
                    }
                    if(winInfo.user1.equals(turnTo)) {
                        winInfo.user1Score++;
                    }else if(winInfo.user2.equals(turnTo)) {
                        winInfo.user2Score++;
                    }
                    this.winInfo.put(key, winInfo);
                } else {
                    this.turnTo = turnTo;
                }
                qiPanLog.add(map);
                break;
            case "JOIN_SPECTOR":
                if (this.user2.name.equals(operate)) {
                    this.user2 = new User();
                }
                if (this.user1.name.equals(operate)) {
                    this.user1 = new User();
                }
                if (!this.spector.contains(operate)) {
                    this.spector.add(operate);
                }
                break;
            case "RESET":
                if (this.roomState == 2) {
                    // 正常的重置游戏
                    resetGame();
                } else if (this.roomState == 1) {
                    if (this.black.equals(operate)) {
                        this.turnTo = this.white;
                    } else if (this.white.equals(operate)) {
                        this.turnTo = this.black;
                    }
                    type = "WIN";
                    this.roomState = 2;
                } else {
                    returnValue.setType("ERROR");
                    returnValue.setOtherMessage("还未开始游戏，你在认输什么？");
                    return returnValue;
                }
        }
        returnValue.setX(x);
        returnValue.setY(y);
        returnValue.setOperator(operate);
        returnValue.setType(type);
        returnValue.setValue(this);
        return returnValue;
    }

    public void resetGame() {
        this.roomState = 0;
        this.turnTo = "";
        this.user1.status = 0;
        this.user2.status = 0;
//        this.black = "";
//        this.white = "";
        this.qiPanLog.clear();
        this.qiPanInfo = new short[SIZE][SIZE];
    }

    // 检查胜利条件的方法
    public boolean checkWin(int x, int y, short player) {
        // 检查水平方向
        if (checkDirection(x, y, 1, 0, player)) return true;
        // 检查垂直方向
        if (checkDirection(x, y, 0, 1, player)) return true;
        // 检查左上到右下的对角线
        if (checkDirection(x, y, 1, 1, player)) return true;
        // 检查右上到左下的对角线
        if (checkDirection(x, y, 1, -1, player)) return true;
        return false;
    }

    // 检查特定方向上的连续棋子
    private boolean checkDirection(int x, int y, int dx, int dy, short player) {
        int count = 0;
        for (int i = -4; i <= 4; i++) {
            int nx = x + i * dx;
            int ny = y + i * dy;
            if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE && qiPanInfo[nx][ny] == player) {
                count++;
                if (count == 5) {
                    return true;
                }
            } else {
                count = 0;
            }
        }
        return false;
    }

    public void joinUser(String user, String sessionId) {
        this.spector.add(user);
        this.sessionUserMap.put(sessionId, user);
    }

    /**
     * 春秋
     * 通过sessionId 移除房间内用户
     *
     * @param sessionId 用户对应的sessionId
     * @return 当前房间信息
     */
    public WuZiQiRoomInfo removeUserBySessionId(String sessionId) {
        String sessionUser = sessionUserMap.get(sessionId);
        if (this.spector.contains(sessionUser)) {
            this.spector.remove(sessionUser);
        } else {
            if (this.user1.name.equals(sessionUser)) {
                this.user1 = new User();
            } else if (this.user2.name.equals(sessionUser)) {
                this.user2 = new User();
            } else {
                log.error("removeUserBySessionId  没有此用户");
            }
        }
        this.sessionUserMap.remove(sessionId);
//        this.spector.remove(sessionUser);
        return this;
    }

}
